Introductions: Hi, I'm .... I'll be co-facilitating 'Programming with Python' with [our mentors names] and [our volunteers names]. If you would like to follow along and type in some of the snippets of code that we demo, our volunteers can assist you in setting up your computer.

Let's begin by giving a quick recap on what we did in the earlier workshops today. In the first workshop we learned about numbers, variables, strings, booleans, and making choices with the use of if-statements. In the second workshop we added lists and looping to our skills. Along the way we used a few functions, such as the built-in functions, print() and len().

In this workshop, we're going to go a little further in depth into functions and Python modules.

Functions

We have already seen a few functions (recall len() for calculating list and string lengths and sum() for summing lists).

Python also lets us make our own functions.

We can use functions for a number of things:

  • We can use functions to break down a problem into parts. It makes the code more readable and is easier to understand. This is called 'program decomposition' or 'factoring'.
  • Functions can also be used instead of using the same lines of code at different times throughout a program. We call this 'code reuse' and what it does is simply reduce duplication of code.
  • We can also use functions for 'abstraction' or 'simplification'. Using functions allows us to hide all of the details involved and put them into one place and simply call the function to execute the lines of code.

Let's start with an example. Say we have a program that wishes someone a happy birthday:


In [ ]:
print("Happy Birthday to you,")
print("Happy Birthday to you,")
print("Happy Birthday, dear Jessica!")
print("Happy Birthday to you!")

We can make this code into a function like so. Let's take a quick look at what we have here.


In [ ]:
def happy_birthday_jessica():
    print("Happy Birthday to you,")
    print("Happy Birthday to you,")
    print("Happy Birthday, dear Jessica!")
    print("Happy Birthday to you!")

The top part is called the 'header' of the function. The header contains the keyword, 'def', the name of the function, a parameter, and a colon.

The keyword 'def' is short for 'define', and it's how we let Python know that we are creating, that is, defining our new function.

The name of our function is 'happy_birthday_jessica'. It has 0 parameters.

The body of our function contains four print lines. We need to indent these lines, and any other lines of code in function's body, by 4 spaces.

Notice that nothing was printed out after we defined our function. To use our function we need to call it, like this:


In [ ]:
happy_birthday_jessica()

Don't forget those parenthesis. Without the parenthesis Python wouldn't know we were trying to call our function, it would just give us the value.


In [ ]:
happy_birthday_jessica

We can create a slew of functions named in a similar fashion:


In [ ]:
def happy_birthday_rise():
    print("Happy Birthday to you,")
    print("Happy Birthday to you,")
    print("Happy Birthday, dear Rise!")
    print("Happy Birthday to you!")

We can call each of these functions like so: (Trey) Remember that we have to type all this in the shell line-by-line


In [ ]:
happy_birthday_jessica()

In [ ]:
happy_birthday_rise()

We can even group those calls to each function into a main() function and just call main() which will then call each of our functions!

(Trey) I think this main function part is confusing. I'm not sure it would translate well to the shell I vote for removing it


In [ ]:
def happy_birthday_jessica():
    print("Happy Birthday to you,")
    print("Happy Birthday to you,")
    print("Happy Birthday, dear Jessica!")
    print("Happy Birthday to you!")

def happy_birthday_rise():
    print("Happy Birthday to you,")
    print("Happy Birthday to you,")
    print("Happy Birthday, dear Rise!")
    print("Happy Birthday to you!")

def main():
    happy_birthday_jessica()
    happy_birthday_rise()

main()

Ok, now, let's work on reusing our code so that we reduce code duplication.

Wouldn't it be cool if we could pass a name into our function so we don't need to write a different function for every name?

Python allows us to do just that with function parameters. We can add a parameter by typing a variable name in between the parethesis after our function name. We can then use the parameter variable in our function.

We'll create a new function called 'happy_birthday', and add a parameter, 'name'.


In [ ]:
def happy_birthday(name):
    print("Happy Birthday to you,")
    print("Happy Birthday to you,")
    print("Happy Birthday, dear " + name + "!")
    print("Happy Birthday to you!")

To execute or run our new function, we simply call it by its name, 'happy_birthday' and pass a value in between the parenthesis, such as the string, 'Trey'.


In [ ]:
happy_birthday("Trey")

Let's get a little bolder and make a list of names that we can loop over and then pass each one into our 'happy_birthday' function. What we get is the same result as the other earlier lines of code!


In [ ]:
names = ["Jessica", "Rise", "Trey"]
for name in names:
    happy_birthday(name)

A function can take more than one parameter (2, 3, or more)

So let's change our function, happy_birthday, by giving it two parameters, 'first_name' and 'last_name'.


In [ ]:
def happy_birthday(first_name, last_name):   # Our new function has two parameters
    print("Happy Birthday to you,")
    print("Happy Birthday to you,")
    print("Happy Birthday, dear " + first_name + " " + last_name + "!")
    print("Happy Birthday to you!")

So let's see what happens if we give our function two string values, one for 'first_name' and another for 'last_name'.


In [ ]:
happy_birthday("Rise", "Riyo")

We could also pass in variables as parameter values to the function. Let's assign the string, "Alain" to the variable, 'first', and the string, "Domissy" to the variable, 'last'.


In [ ]:
first = "Alain"
last = "Domissy"
# Now we will pass these variables to our function
happy_birthday(first, last)

Here we have a new function, 'how_many_cupcakes_to_make'. We are going to pass it one value to its parameter, 'num_of_cupcakes'. We'll have it calculate the number of cupcakes, and then return this value and print it out.


In [75]:
def how_many_cupcakes_to_make(num_of_cupcakes):
    # Multiply the number of cupcakes by 2
    return 2 * num_of_cupcakes

print how_many_cupcakes_to_make(15)


30

In [ ]:
number_of_guests = 20
number_of_cupcakes = 2
print flooring_area(kitchen_width, kitchen_length)

So now we have two functions: one called 'myfunction' and the other called 'flooring_area'. Let's be lazy... Let's execute those two functions by calling them within a new function called 'ee


In [ ]:
def execute_our_two_functions():
    myfunction("Carol","Willing")
    print flooring_area(20,30)

*Do we want to introduce functions with positional and keyword arguments?

Modules

Modules are used to make a programmer's life easier. A module is used to group functions, variables, and other things together in an understandable bundle.

Modules can be used to do useful things - games, photo manipulation, graphics, financial calculations, and much more


In [ ]:
import random

In [ ]:
random.randint(1,6)

Let's use the random integer function to simulate rolling a die in a game


In [ ]:
vegas_die_1 = random.randint(1,6)
vegas_die_2 = random.randint(1,6)
print ("First die: " + str(vegas_die_1))
print ("Second die: " + str(vegas_die_2))
print ("You rolled a " + str(vegas_die_1 + vegas_die_2))

In [ ]:
random.choice('abcdefghijklmnopqrstuvwxyz')

choice is a function in the random module that returns an item

Modules and functions can make things really simple to do. For example we could in a few lines of code get and display a YouTube video


In [ ]:
from IPython.display import YouTubeVideo
# a tutorial about Python at PyCon 2014 in Montreal, Canada by Jessica McKellar
YouTubeVideo('MirG-vJOg04')

In [ ]: